"""
支付服务模块
处理各类支付方式的创建、验证和回调处理
"""
from sqlmodel import Session, select
from typing import Dict, Any, Optional
import requests
import hashlib
import hmac
import time
import json
import logging
from datetime import datetime
from app.models.order_models import Payment, Order, PaymentStatus, PaymentMethod, OrderStatus

logger = logging.getLogger(__name__)


class PaymentService:
    """
    支付服务类
    提供支付创建、验证和处理支付回调等功能
    """
    
    def __init__(self, db: Session):
        """
        初始化支付服务
        
        Args:
            db (Session): 数据库会话对象
        """
        self.db = db
        
        # 支付宝配置参数
        self.alipay_config = {
            'app_id': 'your_app_id',
            'gateway': 'https://openapi.alipay.com/gateway.do',
            'private_key': 'your_private_key',
            'alipay_public_key': 'alipay_public_key'
        }
        
        # 微信支付配置参数
        self.wechat_config = {
            'app_id': 'your_app_id',
            'mch_id': 'your_mch_id',
            'api_key': 'your_api_key',
            'notify_url': 'your_notify_url'
        }
    
    def create_payment(self, order: Order, payment_method: PaymentMethod) -> Dict[str, Any]:
        """
        创建支付
        根据订单信息和支付方式创建支付记录
        
        Args:
            order (Order): 订单对象
            payment_method (PaymentMethod): 支付方式枚举值
            
        Returns:
            Dict[str, Any]: 支付相关数据
            
        Raises:
            ValueError: 当支付方式不支持时抛出
            Exception: 当创建支付失败时抛出
        """
        try:
            # 生成唯一的支付编号
            payment_number = f"P{order.order_number}{int(time.time())}"
            
            # 创建支付记录
            payment = Payment(
                order_id=order.id,
                payment_number=payment_number,
                amount=order.total_amount,
                currency=order.currency,
                payment_method=payment_method,
                status=PaymentStatus.PENDING
            )
            
            # 保存到数据库
            self.db.add(payment)
            self.db.commit()
            self.db.refresh(payment)
            
            # 根据支付方式创建对应的支付请求数据
            if payment_method == PaymentMethod.ALIPAY:
                payment_data = self._create_alipay_payment(payment)
            elif payment_method == PaymentMethod.WECHAT:
                payment_data = self._create_wechat_payment(payment)
            else:
                raise ValueError("不支持的支付方式")
            
            # 保存支付数据
            payment.payment_data = payment_data
            self.db.commit()
            
            return payment_data
            
        except Exception as e:
            # 出现异常时回滚数据库事务
            self.db.rollback()
            logger.error(f"创建支付失败: {str(e)}")
            raise
    
    def _create_alipay_payment(self, payment: Payment) -> Dict[str, Any]:
        """
        创建支付宝支付请求
        
        Args:
            payment (Payment): 支付记录对象
            
        Returns:
            Dict[str, Any]: 支付宝支付请求数据
        """
        biz_content = {
            'out_trade_no': payment.payment_number,
            'total_amount': str(payment.amount),
            'subject': f'3D定制商品 - 订单{payment.order.order_number}',
            'product_code': 'FAST_INSTANT_TRADE_PAY'
        }
        
        return {
            'payment_url': f"alipay://payment?order={payment.payment_number}",
            'biz_content': biz_content
        }
    
    def _create_wechat_payment(self, payment: Payment) -> Dict[str, Any]:
        """
        创建微信支付请求
        
        Args:
            payment (Payment): 支付记录对象
            
        Returns:
            Dict[str, Any]: 微信支付请求数据
        """
        params = {
            'appid': self.wechat_config['app_id'],
            'mch_id': self.wechat_config['mch_id'],
            'nonce_str': self._generate_nonce_str(),
            'body': f'3D定制商品 - 订单{payment.order.order_number}',
            'out_trade_no': payment.payment_number,
            'total_fee': int(payment.amount * 100),  # 微信支付单位为分
            'spbill_create_ip': '127.0.0.1',
            'notify_url': self.wechat_config['notify_url'],
            'trade_type': 'APP'
        }
        
        # 生成签名
        params['sign'] = self._generate_wechat_sign(params)
        
        return {
            'payment_params': params,
            'prepay_id': 'simulated_prepay_id'
        }
    
    def verify_payment_callback(self, payment_method: PaymentMethod, data: Dict[str, Any]) -> bool:
        """
        验证支付回调签名
        
        Args:
            payment_method (PaymentMethod): 支付方式枚举值
            data (Dict[str, Any]): 回调数据
            
        Returns:
            bool: 签名验证结果
        """
        if payment_method == PaymentMethod.ALIPAY:
            return self._verify_alipay_callback(data)
        elif payment_method == PaymentMethod.WECHAT:
            return self._verify_wechat_callback(data)
        return False
    
    def _generate_nonce_str(self, length=32):
        """
        生成随机字符串
        
        Args:
            length (int): 字符串长度，默认32位
            
        Returns:
            str: 随机字符串
        """
        import random
        import string
        return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
    
    def _generate_wechat_sign(self, params: Dict[str, Any]) -> str:
        """
        生成微信支付签名
        
        Args:
            params (Dict[str, Any]): 参与签名的参数
            
        Returns:
            str: MD5签名结果
        """
        # 按参数名排序
        sorted_params = sorted(params.items())
        # 拼接参数
        sign_str = '&'.join([f"{k}={v}" for k, v in sorted_params if v])
        # 添加API密钥
        sign_str += f"&key={self.wechat_config['api_key']}"
        # MD5加密并转大写
        return hashlib.md5(sign_str.encode()).hexdigest().upper()
    
    def _verify_alipay_callback(self, data: Dict[str, Any]) -> bool:
        """
        验证支付宝回调签名
        
        Args:
            data (Dict[str, Any]): 回调数据
            
        Returns:
            bool: 签名验证结果
        """
        return True
    
    def _verify_wechat_callback(self, data: Dict[str, Any]) -> bool:
        """
        验证微信支付回调签名
        
        Args:
            data (Dict[str, Any]): 回调数据
            
        Returns:
            bool: 签名验证结果
        """
        return True
    
    def handle_payment_success(self, payment_number: str):
        """
        处理支付成功事件
        更新支付记录和关联订单的状态
        
        Args:
            payment_number (str): 支付编号
        """
        # 查询支付记录
        payment = self.db.exec(
            select(Payment).where(Payment.payment_number == payment_number)
        ).first()
        
        if payment:
            # 更新支付状态
            payment.status = PaymentStatus.SUCCESS
            payment.paid_at = datetime.utcnow()
            
            # 更新订单状态
            order = payment.order
            order.payment_status = PaymentStatus.SUCCESS
            order.status = OrderStatus.PAID
            
            # 提交数据库更改
            self.db.commit()
            logger.info(f"支付成功处理: {payment_number}")